package com.bytz.modules.cms.auditBatch.service.change;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bytz.common.exception.BytzBootException;
import com.bytz.common.util.RedisUtil;
import com.bytz.modules.cms.auditBatch.service.IChangeService;
import com.bytz.modules.cms.common.constants.CmsConstant;
import com.bytz.modules.cms.common.util.CmsCacheKeyUtil;
import com.bytz.modules.cms.productLine.entity.ProductLineLevel;
import com.bytz.modules.cms.productLine.entity.ProductLineLevelChange;
import com.bytz.modules.cms.productLine.mapper.ProductLineLevelChangeMapper;
import com.bytz.modules.cms.productLine.service.IProductLineLevelService;
import com.bytz.modules.cms.user.constants.AuditBatchConstants;
import com.bytz.modules.cms.user.service.IAuditBatchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class BatchProductLineLevelChangeServiceImpl extends ServiceImpl<ProductLineLevelChangeMapper, ProductLineLevelChange> implements IChangeService<ProductLineLevelChange> {

    @Autowired
    private IProductLineLevelService lineLevelService;

    @Autowired
    private IAuditBatchService auditBatchService;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncChange(String batchId) {

        List<ProductLineLevelChange> changeList = lambdaQuery()
                .eq(ProductLineLevelChange::getAuditBatchId, batchId)
                .eq(ProductLineLevelChange::getSyncStatus, AuditBatchConstants.SyncStatus.WAITING_SYNC)
                .orderByDesc(ProductLineLevelChange::getCreateTime)
                .list();

        if (CollectionUtil.isEmpty(changeList)) {
            return;
        }

        Map<String, List<ProductLineLevelChange>> levelGroup = changeList.stream()
                .collect(Collectors.groupingBy(ProductLineLevelChange::getProductLineLevelId));

        List<ProductLineLevel> updateList = levelGroup.keySet().stream().map(levelId -> {
            ProductLineLevel updateEntity = new ProductLineLevel();
            updateEntity.setId(levelId);

            levelGroup.get(levelId).stream().findFirst().ifPresent(oldest -> {

                updateEntity.setDiscountRatio(oldest.getDiscountRatio());
                updateEntity.setEffectTime(LocalDateTime.now());
            });
            return updateEntity;
        }).collect(Collectors.toList());

        updateSyncData(batchId, updateList);

        // 清除计算价格时用的产品线等级缓存
        Set<String> keys = updateList.stream()
                .map(level -> CmsCacheKeyUtil.getProductLineLevelKey(CmsConstant.CachePrefixes.PRODUCT_LINE_LEVEL, level.getId()))
                .collect(Collectors.toSet());

        redisUtil.del(keys);
    }

    /**
     * 更改auditBatch表 将对应id设置为已同步
     * 更改change表 对应batchId设置为已同步
     * 更新对应的主表
     */
    private void updateSyncData(String batchId, List<ProductLineLevel> updateList) {

        lineLevelService.updateBatchById(updateList);

        lambdaUpdate()
                .eq(ProductLineLevelChange::getAuditBatchId, batchId)
                .set(ProductLineLevelChange::getSyncStatus, AuditBatchConstants.SyncStatus.SYNCED)
                .update();

        auditBatchService.setStatusSynced(batchId);
    }

    @Override
    public List<ProductLineLevelChange> getByBatchId(String batchId) {
        return lambdaQuery()
                .eq(ProductLineLevelChange::getAuditBatchId, batchId)
                .list();
    }

    @Override
    public void removeByBatchId(String batchId) {
        lambdaUpdate().eq(ProductLineLevelChange::getAuditBatchId, batchId).remove();
    }

    @Override
    public SFunction<ProductLineLevelChange, String> getKeyExtractor() {
        return ProductLineLevelChange::getProductLineLevelId;
    }

    @Override
    public List<ProductLineLevelChange> importExcel(List<ProductLineLevelChange> models) {

        Set<String> categoryNames = models.stream().map(ProductLineLevelChange::getLevelName).collect(Collectors.toSet());
        Map<String, ProductLineLevel> levelNameMap = lineLevelService.getByNames(categoryNames)
                .stream().collect(Collectors.toMap(ProductLineLevel::getLevelName, t -> t));

        models.forEach(change -> {
            ProductLineLevel lineLevel = levelNameMap.get(change.getLevelName());
            if (lineLevel == null) {
                throw new BytzBootException(String.format("找不到【%s】对应的等级", change.getLevelName()));
            }
            change.setProductLineLevelId(lineLevel.getId());
            change.setProductLineId(lineLevel.getProductLineId());
            change.setProductLineName(lineLevel.getProductLineName());

            change.setDiscountRatio(change.getDiscountRatio().divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP));
        });
        return models;
    }
}
